import * as echarts from 'echarts'
import type {
  EchartsOptions,
  ChartsParams,
  DataType,
  ChartType,
  ChartsConfig,
} from './types/charts'
import createBarOption from './chart/createBarOption'
import createLineOption from './chart/createLineOption'
import createPieOption from './chart/createPieOption'
import { createTitle, createLegend, createTooltip } from './chart/createCommon'

class Charts {
  chart: echarts.ECharts | null = null
  chartType: ChartType = 'line'
  chartOptions: EchartsOptions = {}
  container: string = ''
  data: DataType
  options = {}
  custom: boolean = false

  constructor(options: ChartsParams) {
    this.container = options.container
    this.data = options.data
    this.chartType = options.type
    this.options = options.options || {}
    this.custom = options.custom || false
    this.init()

    return this
  }
  init() {
    this.chartOptions = this.getOptioins()
    this.chart = echarts.init(document.getElementById(this.container))
    this.chart.setOption(this.chartOptions)
    window.addEventListener('resize', this.reset)
    return this
  }
  getOptioins() {
    if (this.custom) {
      return this.options
    } else {
      return createOptions(this.options, this.chartType, this.data)
    }
  }
  reReader() {
    if (!this.chart) {
      this.init()
    } else {
      this.chart.dispose()
      this.chartOptions = this.getOptioins()
      this.chart = echarts.init(document.getElementById('chart'))
      this.chart.setOption(this.chartOptions)
    }
    return this
  }
  updated() {
    this.chart?.setOption(this.chartOptions)
    return this
  }
  reset() {
    this.chart?.resize()
    return this
  }

  setOptionsCB(cb: (options: EchartsOptions) => EchartsOptions) {
    this.chartOptions = cb(this.chartOptions)
    return this
  }

  setOptions(options: EchartsOptions | object | unknown, key?: string) {
    if (!key) {
      this.chartOptions = options as EchartsOptions
    } else {
      this.chartOptions[key] = options
    }
    return this
  }
  setTitle(title: object) {
    this.chartOptions.title = title
    return this
  }
  setLegend(legend: object) {
    this.chartOptions.legend = legend
    return this
  }
  setTooltip(tooltip: object) {
    this.chartOptions.tooltip = tooltip
    return this
  }
  setXAxis(xAxis: object) {
    this.chartOptions.xAxis = xAxis
    return this
  }
  setYAxis(yAxis: object) {
    this.chartOptions.yAxis = yAxis
    return this
  }
  setSeries(series: []) {
    this.chartOptions.series = series
    return this
  }
  destroy() {
    this.chart?.dispose()
    window.removeEventListener('resize', this.reset)
    this.chart = null
  }
}

export const createOptions = (options: ChartsConfig, type: ChartType, data: DataType) => {
  let chartOptions: EchartsOptions = {}

  const title = createTitle(options)
  if (Object.keys(title).length > 0) {
    chartOptions.title = title
  }

  const legend = createLegend(options)
  if (Object.keys(legend).length > 0) {
    chartOptions.legend = legend
  }

  const tooltip = createTooltip(options)
  if (Object.keys(tooltip).length > 0) {
    chartOptions.tooltip = tooltip
  }
  // other options
  const keys = Object.keys(options)
  for (let i = 0; i < keys.length; i++) {
    const key = keys[i]
    if (['title', 'legend', 'tooltip', 'xAxis', 'yAxis', 'series'].includes(key)) {
      continue
    }
    chartOptions[key] = options[key]
  }

  switch (type) {
    case 'bar':
      chartOptions = createBarOption(chartOptions, options, data)
      break
    case 'line':
      chartOptions = createLineOption(chartOptions, options, data)
      break
    case 'pie':
      chartOptions = createPieOption(chartOptions, options, data)
      break
  }

  return chartOptions
}

export default Charts
